#!/bin/bash
#
# Copyright (c) 2020 NVI, Inc.
#
# This file is part of FSL10 Linux distribution.
# (see http://github.com/nvi-inc/fsl10).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

# For systems with GPT LVM RAID arrays, tries to reset everything on second disk

usage() { echo "Usage: $0 [-A][-h]"; echo -e "  where\t-A\tAllow \"Secondary\" disk to be loaded at start"; echo -e "  \t-h\tdisplay this help and exit"; }

ACCEPT_LOAD=0
DRY_RUN=0
VERBOSE=0
while getopts "Anvh" arg; do
	case $arg in
		A)
			ACCEPT_LOAD=1
			;;
		n)
			DRY_RUN=1
			;;
		v)
			VERBOSE=1
			;;
		h | *)
			usage
			exit 0
			;;
	esac
done

[ $DRY_RUN -eq 0 ] || echo -e "\n!! NB: running in DRY RUN mode ie. no action will actually be taken !!\n"

disk="/dev/sdb"
devname=$(basename $disk)
lockf=/tmp/.accept_load

# Now get the user to load the Secondary disk
if [ -b $disk ] && [ $ACCEPT_LOAD == 0 ] && ([ ! -O $lockf ] || [ "$(cat $lockf)" != "$(lsblk --nodeps -no serial $disk)" ]); then
	echo "ERROR:\"Secondary\" disk $disk must not be loaded before start of script"
	echo "(You may want to use the '-A' option to [A]llow if this is intentional)"
	exit 1
fi
if [ ! -b $disk ]; then
	while [ ! -b $disk ]; do
		echo  -n -e "\rWaiting for disk $disk to be loaded, use 'Control-C' to safely abort ... "
		sleep 1
	done
	echo  -n -e "\r                                                                              "
	echo  -n -e "\rWaiting for disk $disk to settle ... "
	udevadm settle
	sleep 2
	echo $(lsblk --nodeps -no serial $disk) > $lockf
	echo -e "done.\n"
fi

if grep "/boot/efi" /proc/mounts | grep -q "$disk"; then
	# Ensure the primary disk is mounted on /boot/efi (not the secondary)
	umount /boot/efi
	mount /dev/sda1 /boot/efi
fi

# Perform sanity checks on secondary disk now that it's available
if mdadm --detail /dev/md0 | grep -q $disk; then
	echo "ERROR: \"Secondary\" disk $disk is currently part of RAID /dev/md0!!"
	exit 1
fi
if grep -q ^$disk /proc/mounts; then
	echo "ERROR: Some part of \"Secondary\" disk $disk is mounted!!"
	exit 1
fi
if [ $(cat /sys/block/md0/size) -gt $(cat /sys/block/$devname/size) ]; then
	echo "ERROR: \"Secondary\" device $devname is too small to house RAID /dev/md0"
	exit 1
fi
if [ "$(cat /sys/block/$devname/removable)" != "0" ]; then
	echo "WARNING: \"Secondary\" disk $disk is removable:"
	echo -n " $disk: "$(lsblk --nodeps -no tran $disk | tr [:lower:] [:upper:])
	echo -n " "$(lsblk --nodeps -no type $disk)
	echo -n ", model" $(lsblk --nodeps -no model $disk)
	echo ", s/n "$(lsblk --nodeps -no serial $disk)
fi

if [ $VERBOSE -eq 0 ]; then
	echo -n "Are you sure you wish to blank \"Secondary\" disk $disk (y=yes, n=no)? "
	badans=true
	while [ "$badans" = "true" ]; do
		read ans
		case "$ans" in
		y|yes)	badans=false
			;;
		n|no)	echo -e "Aborting."
			exit 0
			;;
		*)	echo -e "Please answer with y=yes or n=no : \c"
		esac
	done
fi

for part in $(cd /dev/;ls $devname?* 2>/dev/null); do
	partnum=$(echo $part | sed -e "s/$devname//")
	[ $VERBOSE -ne 0 ] && sgdisk -i$partnum $disk | head -n 1
	raid=$(grep $part /proc/mdstat | cut -d' ' -f1)
	if [ "$raid" = "md0" ]; then 
		# Belt _and_ braces!
        	echo "ERROR: \"Secondary\" disk $disk is currently part of RAID /dev/md0!!"
		exit 1
	elif [ ! -z $raid ]; then
		if grep ^"$raid" /proc/mdstat | grep -q " sda"; then
        		echo -n "ERROR: \"Primary\" disk /dev/sda is in a common RAID array: "
			mdadm --detail --scan /dev/$raid
			exit 1
		fi
		# Part of a foreign RAID volume
		if [ $VERBOSE -ne 0 ]; then
			echo -n "Detected /dev/$part in \"foreign\" RAID array: "
			mdadm --detail /dev/$raid
		fi
		if pvdisplay /dev/$raid 2>/dev/null | grep -q "/dev/$raid" ; then
			VG=$(pvs --noheadings -o vg_name /dev/$raid | tr -d " ")
			VG_UUID=$(pvs --noheadings -o vg_uuid /dev/$raid | tr -d " ")
			LVS=$(pvs --noheadings -o lv_name /dev/$raid | tr -d " " | sort -u)
			if [ $VERBOSE -ne 0 ]; then
				echo "In use as LVM physical volume:"
				pvdisplay /dev/$raid
				echo -n "Which contains LV(s):"
				for lv in $LVS; do
					echo -n " $VG/$lv"
				done; echo
				echo -n "Delete RAID+LVM contents (Control-C aborts)? "
				read $ans
				[ $DRY_RUN -eq 0 ] && lvremove -v -f -S vg_uuid=$VG_UUID
				[ $DRY_RUN -eq 0 ] && vgremove -v -f -S vg_uuid=$VG_UUID
				[ $DRY_RUN -eq 0 ] && pvremove -v -ff -y /dev/$raid
			else
				[ $DRY_RUN -eq 0 ] && lvremove -f -S vg_uuid=$VG_UUID > /dev/null
				[ $DRY_RUN -eq 0 ] && vgremove -f -S vg_uuid=$VG_UUID > /dev/null
				[ $DRY_RUN -eq 0 ] && pvremove -ff -y /dev/$raid > /dev/null
			fi
		elif [ $VERBOSE -ne 0 ]; then
			echo -n "Delete RAID contents (Control-C aborts)? "
			read $ans
		fi
		if [ $VERBOSE -ne 0 ]; then
			[ $DRY_RUN -eq 0 ] && mdadm -S /dev/$raid
			[ $DRY_RUN -eq 0 ] && mdadm --zero-superblock --force /dev/$part 2>/dev/null
		else
			[ $DRY_RUN -eq 0 ] && mdadm -S /dev/$raid > /dev/null 2>&1
			[ $DRY_RUN -eq 0 ] && mdadm --zero-superblock --force /dev/$part >/dev/null 2>&1
		fi
	else
		# Standalone partition or part of a local RAID volume
		if [ $VERBOSE -ne 0 ] && [ ! -z "$(sgdisk -i$partnum $disk | grep 'BIOS boot')" ]; then
			echo "Detected BIOS boot partition: /dev/$part"
			echo -n "Wipe partition (Control-C aborts)? "
			read $ans
		elif [ $VERBOSE -ne 0 ] && [ ! -z "$(sgdisk -i$partnum $disk | grep 'EFI System')" ]; then
			echo "Detected EFI System partition: /dev/$part"
			echo -n "Wipe partition (Control-C aborts)? "
			read $ans
		elif [ $VERBOSE -ne 0 ] && [ ! -z "$(sgdisk -i$partnum $disk | grep 'Linux filesystem')" ]; then
			echo "Detected Linux filesystem partition: /dev/$part"
			tune2fs -l /dev/$part
			echo -n "Wipe partition (Control-C aborts)? "
			read $ans
		elif mdadm -b --examine /dev/$part 2>&1 | grep -q ARRAY ; then
			if [ $VERBOSE -ne 0 ]; then
				echo -n "Detected (unused) RAID component: "
				mdadm --examine /dev/$part
				echo -n "Delete RAID contents (Control-C aborts)? "
				read $ans
				[ $DRY_RUN -eq 0 ] && mdadm --zero-superblock --force /dev/$part 2>/dev/null
			else
				[ $DRY_RUN -eq 0 ] && mdadm --zero-superblock --force /dev/$part > /dev/null 2>&1
			fi
		elif pvdisplay /dev/$part 2>/dev/null | grep -q "/dev/$part" ; then
			VG=$(pvs --noheadings -o vg_name /dev/$part | tr -d " ")
			VG_UUID=$(pvs --noheadings -o vg_uuid /dev/$part | tr -d " ")
			LVS=$(pvs --noheadings -o lv_name /dev/$part | tr -d " " | sort -u)
			if [ $VERBOSE -ne 0 ]; then
				echo "Detected LVM physical volume:"
				pvdisplay /dev/$part
				echo -n "Which contains LV(s):"
				for lv in $LVS; do
					echo -n " $VG/$lv"
				done; echo
				echo -n "Delete LVM contents (Control-C aborts)? "
				read $ans
				[ $DRY_RUN -eq 0 ] && lvremove -v -f -S vg_uuid=$VG_UUID
				[ $DRY_RUN -eq 0 ] && vgremove -v -f -S vg_uuid=$VG_UUID 
				[ $DRY_RUN -eq 0 ] && pvremove -v -ff -y /dev/$part
			else
				[ $DRY_RUN -eq 0 ] && lvremove -f -S vg_uuid=$VG_UUID > /dev/null
				[ $DRY_RUN -eq 0 ] && vgremove -f -S vg_uuid=$VG_UUID > /dev/null
				[ $DRY_RUN -eq 0 ] && pvremove -ff -y /dev/$part > /dev/null
			fi
		elif [ $VERBOSE -ne 0 ]; then
			echo "Detected unrecognised partition: /dev/$part"
			echo -n "Wipe partition (Control-C aborts)? "
			read $ans
		fi
	fi
	if [ $VERBOSE -ne 0 ]; then
		echo -n "Wiping partition /dev/$part ... "
		[ $DRY_RUN -eq 0 ] && wipefs -a /dev/$part
		echo -e "done.\n"
	else
		[ $DRY_RUN -eq 0 ] && wipefs -aq /dev/$part > /dev/null
	fi
done
if [ $VERBOSE -ne 0 ]; then
	echo -n "Erase partition table of disk $disk (Control-C aborts)? "
	read $ans
	if $(partprobe -ds $disk | grep -q msdos); then
		[ $DRY_RUN -eq 0 ] && sfdisk --delete $disk
	else
		[ $DRY_RUN -eq 0 ] && sgdisk -Z -o $disk
	fi
	[ $DRY_RUN -eq 0 ] && wipefs -a $disk
else
	if $(partprobe -ds $disk | grep -q msdos); then
		[ $DRY_RUN -eq 0 ] && sfdisk --delete $disk > /dev/null
	else
		[ $DRY_RUN -eq 0 ] && sgdisk -Z -o $disk > /dev/null
	fi
	[ $DRY_RUN -eq 0 ] && wipefs -aq $disk > /dev/null
fi
if [ $DRY_RUN -eq 0 ]; then
	echo -e "\n\"Secondary\" disk $disk is hopefully now blank!"
else
	echo -e "\n\"Secondary\" disk $disk is hopefully _NOT_ blank! ;-)"
fi

exit 0
